/*
 *    Copyright © OpenAtom Foundation.
 *
 *    Licensed under the Apache License, Version 2.0 (the "License");
 *    you may not use this file except in compliance with the License.
 *    You may obtain a copy of the License at
 *
 *         http://www.apache.org/licenses/LICENSE-2.0
 *
 *    Unless required by applicable law or agreed to in writing, software
 *    distributed under the License is distributed on an "AS IS" BASIS,
 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *    See the License for the specific language governing permissions and
 *    limitations under the License.
 */

package com.inspur.edp.udt.designtime.manager.services;


import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.inspur.edp.bef.bizentity.GspBusinessEntity;
import com.inspur.edp.cef.designtime.api.IGspCommonField;
import com.inspur.edp.cef.designtime.api.collection.GspAssociationCollection;
import com.inspur.edp.cef.designtime.api.element.GspAssociation;
import com.inspur.edp.cef.designtime.api.element.GspElementObjectType;
import com.inspur.edp.lcm.metadata.api.IMetadataContent;
import com.inspur.edp.lcm.metadata.api.entity.GspMetadata;
import com.inspur.edp.lcm.metadata.api.service.RefCommonService;
import com.inspur.edp.udt.designtime.api.entity.ComplexDataTypeDef;
import com.inspur.edp.udt.designtime.api.entity.SimpleDataTypeDef;
import com.inspur.edp.udt.designtime.api.entity.UnifiedDataTypeDef;
import com.inspur.edp.udt.designtime.api.entity.element.UdtElement;
import com.inspur.edp.udt.designtime.api.json.UdtElementDeserializer;
import com.inspur.edp.udt.designtime.api.json.UdtElementSerializer;
import com.inspur.edp.udt.designtime.api.utils.UdtUtils;
import com.inspur.edp.udt.designtime.api.utils.UpdateElementUtil;
import com.inspur.edp.udt.designtime.manager.udtmanagerexception.UdtManagerException;
import io.iec.edp.caf.commons.exception.ExceptionLevel;
import io.iec.edp.caf.commons.utils.SpringBeanUtils;
import lombok.experimental.var;

/**
 * 同步字段服务
 */
public class UpdateElementService {
  private final java.util.HashMap<String, GspMetadata> metadataDic = new java.util.HashMap<String, GspMetadata>();
  private String ERRORCODE = "UpdateElementService";
  private static String EXCEPTIONCODE = "UdtManager";
  private RefCommonService lcmDtService;

  private RefCommonService getLcmDtService() {
    if (lcmDtService == null) {
      lcmDtService = SpringBeanUtils.getBean(RefCommonService.class);
    }
    return lcmDtService;

  }

  public static UpdateElementService getInstance() {
    return new UpdateElementService();
  }

  ///#region 批量

  public final void HandleSUdtElements(SimpleDataTypeDef sUdt) {
    UpdateSUdtAssos(sUdt);
  }

  public final void HandleCUdtElements(ComplexDataTypeDef cUdt) {
    for (IGspCommonField ele : cUdt.getElements()) {
      if (!ele.getHasAssociation()) {
        continue;
      }

      for (GspAssociation asso : ele.getChildAssociations()) {
        SetAssoModelInfo(asso);
      }
    }
  }

  ///#endregion

  ///#region 单个字段 选udt

  /**
   * 根据选中的udt元数据更新多值udt字段信息 更新ChildElements,Mapping
   *
   * @return 更新后字段的json序列化
   */
  public final String updateElementWithRefUdt(String refUdtId, String path, String udtElementJson) {
    ObjectMapper mapper = new ObjectMapper();
    SimpleModule module = new SimpleModule();
    module.addDeserializer(IGspCommonField.class, new UdtElementDeserializer());
    module.addSerializer(IGspCommonField.class, new UdtElementSerializer());
    mapper.registerModule(module);
    GspMetadata refUdtMetadata = getLcmDtService().getRefMetadata(refUdtId);

    Object tempVar = null;

    try {
      UdtElement element = (UdtElement) mapper.readValue(udtElementJson, IGspCommonField.class);
      if (element == null) {
        throw new UdtManagerException("", ERRORCODE, "当前字段序列化失败。", null, ExceptionLevel.Error,
            false);
      }

      IMetadataContent content = refUdtMetadata.getContent();
      if (content instanceof UnifiedDataTypeDef) {
        UpdateElementUtil util = new UpdateElementUtil();
        util.updateElementWithRefUdt(element, (UnifiedDataTypeDef) content);

        if (content instanceof SimpleDataTypeDef) {
          element.setUnifiedDataType((SimpleDataTypeDef) content);
        }
      } else {
        throw new UdtManagerException("", ERRORCODE, "未定义的业务字段元数据类型。", null, ExceptionLevel.Error,
            false);
      }

      String eleJson = null;
      eleJson = mapper.writeValueAsString(element);
      return eleJson;
    } catch (JsonProcessingException e) {
      throw new RuntimeException("UdtElement反序列化失败" + e);

    }
  }

  ///#endregion

  ///#region 单个字段 选关联

  /**
   * 若关联为选择udt带出，则带出字段标签="{当前字段标签}_{udt带出字段标签}"
   */
  public final void UpdateFieldWithAsso(IGspCommonField element) {
    if (!element.getHasAssociation()) {
      return;
    }
    for (GspAssociation asso : element.getChildAssociations()) {
      SetAssoModelInfo(asso);
    }
  }

  public final void UpdateSUdtAssos(SimpleDataTypeDef sUdt) {
    if (sUdt.getChildAssociations() != null && sUdt.getChildAssociations().size() > 0) {
      for (GspAssociation asso : sUdt.getChildAssociations()) {
        SetAssoModelInfo(asso);
      }
    }
  }

  ///#endregion

  /**
   * 赋值AssoModelInfo 1.首次选择关联时调用赋值； 2.打开设计器时需调用更新；
   */
  private void SetAssoModelInfo(GspAssociation asso) {

    GspBusinessEntity refModel = (GspBusinessEntity) (
        (GetRefMetadata(asso.getRefModelID()).getContent() instanceof GspBusinessEntity)
            ? GetRefMetadata(asso.getRefModelID()).getContent() : null);
    asso.getAssoModelInfo().setMainObjCode(refModel.getMainObject().getCode());
    asso.getAssoModelInfo().setModelConfigId(refModel.getGeneratedConfigID());
  }

  private GspMetadata GetRefMetadata(String id) {
    if (metadataDic.containsKey(id)) {
      return metadataDic.get(id);
    }
    GspMetadata metadata = getLcmDtService().getRefMetadata(id);
    metadataDic.put(id, metadata);
    return metadata;
  }

  /**
   * 单值udt的子节点关联兼容
   */
  public void handleSimpleUdtChildAsso(SimpleDataTypeDef sUdt) {
    if (sUdt.getObjectType() == GspElementObjectType.Association) {
      handleChildAsso(sUdt.getChildAssociations());
    }
  }

  /**
   * 多值udt的子节点关联兼容
   */
  public void handleComplexUdtChildAsso(ComplexDataTypeDef cUdt) {
    if (cUdt.getElements().size() > 0) {

      for (IGspCommonField ele : cUdt.getElements()) {
        handleChildAsso(ele.getChildAssociations());
      }
    }
  }

  public void handleChildAsso(GspAssociationCollection assos) {
    if (assos != null && assos.size() > 0) {

      for (GspAssociation asso : assos) {
        if (UdtUtils.checkNull(asso.getRefObjectID())) {
          RefCommonService metadataService = SpringBeanUtils.getBean(RefCommonService.class);

          GspMetadata metadata = metadataService.getRefMetadata(asso.getRefModelID());
          if (metadata.getContent() instanceof GspBusinessEntity) {
            asso.setRefObjectID(
                ((GspBusinessEntity) metadata.getContent()).getMainObject().getID());
            asso.setRefObjectCode(
                ((GspBusinessEntity) metadata.getContent()).getMainObject().getCode());
            asso.setRefObjectName(
                ((GspBusinessEntity) metadata.getContent()).getMainObject().getName());
          } else {
            throw new UdtManagerException("", EXCEPTIONCODE,
                "无法加载关联业务实体'{" + asso.getRefModelName() + "}',ID='{" + asso.getRefModelID() + "}'。",
                null,
                ExceptionLevel.Error, false);
          }
        }
      }
    }

  }
}
